前文(Ambari-server开发自定义api)提到ambari-server自定义api,来获取一个表的信息。

现在有一个需求,就是制作一个api,获取两个表的信息。这两个表中的数据是通过一个字段值是否一致来判断是否关联在一起的。

下文会根据每个方法的作用进行说明,没有ambari-server后台开发的经验看起来可能会有些吃力,建议还是多debug后台代码,该文仅作参考。

下面以ambari数据表rackshosts表为例,制作的一条get类型的api,其中根据racks表中的rack_name字段值和hosts表中的rack_info字段值判断数据是否关联。

一、得到多表数据

1. QueryImpl.queryForSubResources()

其中requestedSubResources的值是在对应Type的ResourceDefinition类中定义,例如RackResourceDefinition.java

对应的RackHostResourceDefinition.java

这样的话,requestedSubResources就有值了

2. populatedQueryResults代表你前面查询获取到的数据
3. QueryImpl.getKeyValueMap()

4. QueryImpl.createPredicate()

5. QueryImpl.doQuery()

获取的另一个表中的数据

6. 返回到QueryImpl.execute(),执行getResult()

这里面最重要的就是两个for循环,由两个for循环来判断子资源是否内嵌到父资源内

7. QueryResult queryResult = queryResults.get(parentResource);
  • queryResultqueryResponse代表Rack相关数据
  • 这个方法里面也有相关分页,排序的操作(分页和排序功能没有深入研究
8. 使用for循环来遍历Rack相关的数据 – iterResource

9. 第二个for循环对requestedSubResources进行遍历

10. 又执行了一遍getResult()方法,

TreeNode<Resource> childResult = subResource.getResult(resource).getResultTree();

QueryResult queryResult = queryResults.get(parentResource);

这里得到结果的queryResponse就是子数据了

11. 重中之重

会根据ClusterControllerImpl.getNextResource()来获取下一个资源,如果这里判断为null,进而判断为false,则不会进入for循环,进而会退出二次迭代,然后子数据就没有了。这也是多表数据关联的最重要的一步。

是在QueryImpl.getResult()里面进行操作的。要特别注意。

ClusterControllerImpl.getNextResource() —> .evaluate() —> org.apache.ambari.server.controller.predicate.EqualsPredicate.evaluate()来作判断。

这两个的keyPropertyIds需要对比,必须只有Resource.Type.Rack相同,否则predicate的值就会有变化,进而导致两个表的数据无法进行关联匹配。

org/apache/ambari/server/controller/internal/RackResourceProvider.java

org/apache/ambari/server/controller/internal/RackHostResourceProvider.java

二、最终效果

请求方式:http://ip:8080/api/v1/racks?fields=rack_hosts

请求类型:GET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
href: "http://ip:8080/api/v1/racks?fields=rack_hosts",
items: [
{
href: "http://ip:8080/api/v1/racks/%2Frack1",
rack: {
rack_description: "",
rack_height: "42",
rack_id: 1,
rack_location: "",
rack_name: "/rack1",
rack_type: "Defalut"
},
rack_hosts: [
{
href: "http://ip:8080/api/v1/racks/%2Frack1/rack_hosts/node1.ambari",
Host: {
cpu_count: 2,
disk_info: [
{
available: "40661924",
device: "/dev/sda3",
used: "80735412",
percent: "67%",
size: "121397336",
type: "xfs",
mountpoint: "/"
}
],
host_height: "2",
host_location: "41",
host_name: "node1.ambari",
host_status: "HEALTHY",
host_type: "default",
ip: "ip",
maintenance_state: "OFF",
os_type: "centos7",
ph_cpu_count: 2,
public_host_name: "node1.ambari",
rack_info: "/rack1",
total_mem: 7994320
}
}
]
},
{
href: "http://ip:8080/api/v1/racks/%2Frack2",
rack: {
rack_description: "",
rack_height: "42",
rack_id: 2,
rack_location: "",
rack_name: "/rack2",
rack_type: "Defalut"
},
rack_hosts: [

]
}
]
}

其中rack字段是一个表的数据,rack_hosts字段又是另一个表的数据。